package com.aranandroid.customview.progress

import kotlin.jvm.JvmOverloads
import com.aranandroid.customview.progress.WaveProgressView
import android.animation.ValueAnimator
import android.content.res.TypedArray
import com.aranandroid.customview.R
import android.view.animation.LinearInterpolator
import android.animation.ValueAnimator.AnimatorUpdateListener
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.TypedValue
import android.view.View

/**
 * Created by Chen on 2017/6/4.
 * 水波纹百分比进度条
 */
class WaveProgressView @JvmOverloads constructor(
    context: Context?,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    //进度
    private var mProgress = 0

    //半径
    private var mRadius = DEFAULT_RADIUS

    //进度条的高度
    private var mProgressHeight = 0

    //文字的大小
    private var mTextSize = 0

    //波高
    private var mWaveHeight = 0

    //文字颜色
    private var mTextColor = 0

    //波浪的颜色
    private var mWaveColor = 0

    //圆形边框的颜色
    private var mBorderColor = 0

    //圆形边框的宽度
    private var borderWidth = 0

    //是否隐藏进度文字
    private var isHideProgressText = false

    //进度条的贝塞尔曲线
    private var mBerzierPath: Path? = null

    //用于裁剪的Path
    private var mCirclePath: Path? = null

    // 画圆的画笔
    private var mCirclePaint: Paint? = null

    // 画文字的笔
    private var mTextPaint: Paint? = null

    // 画波浪的笔
    private var mWavePaint: Paint? = null

    // 文字的区域
    private var mTextRect: Rect? = null
    lateinit var mAnimator: ValueAnimator
    private var mMoveX = 0
    private var isStartAnimation = false
    private fun getAttrs(attrs: AttributeSet?) {
        val ta = context.obtainStyledAttributes(attrs, R.styleable.WaveProgressView)
        mRadius = ta.getDimensionPixelSize(R.styleable.WaveProgressView_radius, DEFAULT_RADIUS)
        mProgressHeight = mRadius * 2
        mTextColor = ta.getColor(R.styleable.WaveProgressView_textColor, Color.BLACK)
        mWaveColor = ta.getColor(R.styleable.WaveProgressView_waveColor, Color.GREEN)
        mBorderColor = ta.getColor(R.styleable.WaveProgressView_borderColor, Color.RED)
        borderWidth = ta.getDimensionPixelOffset(
            R.styleable.WaveProgressView_borderWidth, dp2px(
                DEFAULT_BORDER_WIDTH
            )
        )
        mTextSize = ta.getDimensionPixelSize(
            R.styleable.WaveProgressView_textSize, sp2px(
                DEFAULT_TEXT_SIZE
            )
        )
        mWaveHeight = ta.getDimensionPixelSize(
            R.styleable.WaveProgressView_waveHeight, dp2px(
                DEFAULT_WAVE_HEIGHT
            )
        )
        mProgress = ta.getInteger(R.styleable.WaveProgressView_progress, 0)
        isHideProgressText = ta.getBoolean(R.styleable.WaveProgressView_hideText, false)
        ta.recycle()
    }

    private fun initPath() {
        mBerzierPath = Path()
        mCirclePath = Path()
        mCirclePath!!.addCircle(
            mRadius.toFloat(),
            mRadius.toFloat(),
            mRadius.toFloat(),
            Path.Direction.CCW
        )
    }

    private fun initPaint() {
        mWavePaint = Paint()
        mWavePaint!!.color = mWaveColor
        mWavePaint!!.style = Paint.Style.FILL
        mWavePaint!!.isAntiAlias = true
        mCirclePaint = Paint()
        mCirclePaint!!.style = Paint.Style.FILL // 空心画笔
        mCirclePaint!!.color = mBorderColor
        mCirclePaint!!.isAntiAlias = true
        mCirclePaint!!.strokeWidth = borderWidth.toFloat()
        mTextPaint = Paint(Paint.ANTI_ALIAS_FLAG)
        mTextPaint!!.color = mTextColor
        mTextPaint!!.textSize = mTextSize.toFloat()
        mTextRect = Rect()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        //圆形的进度条，正好是正方形的内切圆(这边暂时没有考虑padding的影响)
        setMeasuredDimension(mProgressHeight, mProgressHeight)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        mBerzierPath!!.reset()
        //画曲线
        mBerzierPath!!.moveTo((-mProgressHeight + mMoveX).toFloat(), waveY.toFloat())
        var i = -mProgressHeight
        while (i < mProgressHeight * 3) {

            //圆内最长一个波长
            mBerzierPath!!.rQuadTo(
                (mProgressHeight / 4).toFloat(),
                mWaveHeight.toFloat(),
                (mProgressHeight / 2).toFloat(),
                0f
            )
            mBerzierPath!!.rQuadTo(
                (mProgressHeight / 4).toFloat(),
                -mWaveHeight.toFloat(),
                (mProgressHeight / 2).toFloat(),
                0f
            )
            i += mProgressHeight
        }
        mBerzierPath!!.lineTo(mProgressHeight.toFloat(), mProgressHeight.toFloat())
        mBerzierPath!!.lineTo(0f, height.toFloat())
        mBerzierPath!!.close()

        //画圆
        canvas.drawCircle(mRadius.toFloat(), mRadius.toFloat(), mRadius.toFloat(), mCirclePaint!!)

        //裁剪一个圆形的区域
        canvas.clipPath(mCirclePath!!)
        canvas.drawPath(mBerzierPath!!, mWavePaint!!)


        //开启属性动画使波浪浪起来(这里只需要启动一次)
        if (!isStartAnimation) {
            isStartAnimation = true
            startAnimation()
        }

        //画文字（画文字可不是直接drawText这么简单，要找基线去画）
        var progress = "$mProgress%"
        if (isHideProgressText) {
            progress = ""
        }
        mTextPaint!!.getTextBounds(progress, 0, progress.length, mTextRect)
        canvas.drawText(
            progress, (mRadius - mTextRect!!.width() / 2).toFloat(), (
                    mRadius + mTextRect!!.height() / 2).toFloat(), mTextPaint!!
        )
    }

    private val waveY: Int
        private get() {
            val scale = mProgress * 1f / DEFAULT_MAX_PROGRESS * 1f
            return if (scale >= 1) {
                0
            } else {
                val height = (scale * mProgressHeight).toInt()
                mProgressHeight - height
            }
        }

    private fun startAnimation() {
        mAnimator = ValueAnimator.ofInt(0, mProgressHeight)
        mAnimator.setDuration(2000)
        mAnimator.setRepeatCount(ValueAnimator.INFINITE)
        mAnimator.setInterpolator(LinearInterpolator())
        mAnimator.addUpdateListener(AnimatorUpdateListener { animation ->
            mMoveX = animation.animatedValue as Int
            postInvalidate()
        })
        mAnimator.start()
    }

    /**
     * 设置字体的颜色
     *
     * @param color
     */
    fun setTextColor(color: Int) {
        mTextPaint!!.color = color
    }

    /**
     * 设置波浪的颜色
     *
     * @param color
     */
    fun setWaveColor(color: Int) {
        mWavePaint!!.color = color
    }

    /**
     * 设置
     *
     * @param color
     */
    fun setBorderColor(color: Int) {
        mCirclePaint!!.color = color
    }

    /**
     * 设置隐藏进度文字
     *
     * @param flag
     */
    fun hideProgressText(flag: Boolean) {
        isHideProgressText = flag
    }
    /**
     * 获取当前进度
     *
     * @return
     */
    /**
     * 设置进度
     *
     * @param progress
     */
    var progress: Int
        get() = mProgress
        set(progress) {
            mProgress = progress
            postInvalidate()
        }

    //dp to px
    protected fun dp2px(dpval: Int): Int {
        return TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            dpval.toFloat(),
            resources.displayMetrics
        ).toInt()
    }

    //sp to px
    protected fun sp2px(dpval: Int): Int {
        return TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_SP,
            dpval.toFloat(),
            resources.displayMetrics
        ).toInt()
    }

    companion object {
        /**
         * 默认波长
         */
        private const val DEFAULT_RADIUS = 100

        /**
         * 默认波峰和波谷的高度
         */
        private const val DEFAULT_WAVE_HEIGHT = 5

        /**
         * 默认的最大的进度
         */
        private const val DEFAULT_MAX_PROGRESS = 100

        /**
         * 默认边框宽度
         */
        private const val DEFAULT_BORDER_WIDTH = 2

        /**
         * 默认的进度字体大小
         */
        private const val DEFAULT_TEXT_SIZE = 16
    }

    init {
        getAttrs(attrs)
        initPaint()
        initPath()
    }
}